#include "Component\Physics\Transform.h"
namespace SakuraAge {
SerializedStream& operator&(SerializedStream& ss, Vector2& value2) {
  ss& value2.x;
  ss& value2.y;
  return ss;
}
Vector2 Vector2::operator+(const Vector2& a) const {
  Vector2 b;
  b.x = this->x + a.x;
  b.y = this->y + a.y;
  return b;
}
Vector2 Vector2::operator-(const Vector2& a) const {
  Vector2 b;
  b.x = this->x - a.x;
  b.y = this->y - a.y;
  return b;
}
Vector2 Vector2::operator*(float a) const {
  Vector2 b;
  b.x = this->x * a;
  b.y = this->y * a;
  return b;
}
Vector2 Vector2::operator/(float a) const {
  Vector2 b;
  b.x = this->x / a;
  b.y = this->y / a;
  return b;
}
Vector2 Vector2::operator+=(const Vector2& a) {
  this->x = this->x + a.x;
  this->y = this->y + a.y;
  return *this;
}
Vector2 Vector2::operator-=(const Vector2& a) {
  this->x = this->x - a.x;
  this->y = this->y - a.y;
  return *this;
}
Vector2 Vector2::operator*=(float a) {
  this->x = this->x * a;
  this->y = this->y * a;
  return *this;
}
Vector2 Vector2::operator/=(float a) {
  this->x = this->x / a;
  this->y = this->y / a;
  return *this;
}
void Vector2::RotateAround(const Vector2& center, float angle) {
  float b = x-center.x;
  x = b * cosf(angle) - (y - center.y) * sinf(angle) + center.x;
  y = b * sinf(angle) + (y - center.y) * cosf(angle) + center.y;
}
void Vector2::RotateAround_a(const Vector2& center, float angle) {
  float b = x - center.x;
  angle = angle * PI / 180;
  x = b * cosf(angle) - (y - center.y) * sinf(angle) + center.x;
  y = b * sinf(angle) + (y - center.y) * cosf(angle) + center.y;
}
void Vector2::Rotate(float angle) { 
  float b = x;
  x = x * cosf(angle) - y * sinf(angle);
  y = b * sinf(angle) + y * cosf(angle);
}
void Vector2::Rotate_a(float angle) {
  float b = x;
  x = x * cosf(angle) - y * sinf(angle);
  y = b * sinf(angle) + y * cosf(angle);
}
float Vector2::magnitude() const {
  return std::sqrt(this->x * this->x + this->y * this->y);
}
Vector2 Vector2::normalized() const {
  if (magnitude() == 0) {
    return *this;
  }
  float a = 1 / magnitude();
  Vector2 b = *this;
  b.x *= a;
  b.y *= a;
  return b;
}
void Vector2::Normalized() {
  float a = 1 / magnitude();
  this->x *= a;
  this->y *= a;
}

Transform& SakuraAge::Transform::RotateDeg(float angle) {
  local_rotation += angle;
  return *this;
}
Transform& Transform::RotateRad(float angle) {
  local_rotation += angle / (2 * PI) * 180;
  return *this;
}
Transform& Transform::Move(const Vector2& value) {
  local_position += value;
  return *this;
}
Transform& Transform::Translate(const Vector2& value) {
  local_position += Vector2(value.x * cos(local_rotation * DEG2RAD) -
                                value.y * sin(local_rotation * DEG2RAD),
                            value.x * sin(local_rotation * DEG2RAD) +
                                value.y * cos(local_rotation * DEG2RAD));
  return *this;
}
Vector2 Transform::RotateAround(float angle) {
  return father->position +
         Vector2(local_position.x * cos(local_rotation * DEG2RAD) -
                     local_position.y * sin(local_rotation * DEG2RAD),
                 local_position.x * sin(local_rotation * DEG2RAD) +
                     local_position.y * cos(local_rotation * DEG2RAD));
}
void Transform::Serialize(SerializedStream& ss) { 
  this->Component::Serialize(ss);
  ss& local_position;
  ss& local_rotation;
  ss& local_scale;
  ss& (ObjectRef&)father;
  ss&& children;
}
Transform::Transform() : Component() { father = nullptr; }
Vector2 Transform::GetPosition() {
  if (father != nullptr)
    return father->GetPosition() + local_position;
  else
    return local_position;
}
void Transform::SetPosition(Vector2 value) {
  local_position =
      Vector2(value.x - (father == nullptr ? 0 : father->GetPosition().x),
              value.y - (father == nullptr ? 0 : father->GetPosition().y));
}
float Transform::GetRotation() {
  if (father != nullptr)
    return father->rotation + local_rotation;
  else
    return local_rotation;
}
void Transform::SetRotation(float value) {
  if (father != nullptr)
    local_rotation = rotation - father->rotation;
  else
    local_rotation = value;
}
Vector2 Transform::GetScale() {
  if (father != nullptr)
    return father->local_scale + local_scale;
  else
    return local_scale;
}
void Transform::SetScale(Vector2 value) {
  local_scale =
      Vector2(value.x / ((father == nullptr) ? 1 : (father->scale).x),
              value.y / ((father == nullptr) ? 1 : (father->scale).y));
}
}  // namespace SakuraAge
